package cn.funeralobjects.project.sshd.utils;

import org.apache.commons.io.FileUtils;
import org.springframework.util.Base64Utils;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.util.Arrays;

/**
 * @author FuneralObjects
 * Create date: 2020/8/5 4:43 AM
 */
public class PublicKeyUtils {

    private static final String RSA_KEY = "ssh-rsa";

    private static PublicKey decodePublicKey(byte[] keyBytes) throws GeneralSecurityException {
        // strip any newline chars
        while (keyBytes[keyBytes.length - 1] == 0x0a || keyBytes[keyBytes.length - 1] == 0x0d) {
            keyBytes = Arrays.copyOf(keyBytes, keyBytes.length - 1);
        }
        byte[] decodeBuffer = Base64Utils.decode(keyBytes);
        ByteBuffer bb = ByteBuffer.wrap(decodeBuffer);
        int len = bb.getInt();
        byte[] type = new byte[len];
        bb.get(type);
        if (RSA_KEY.equals(new String(type))) {
            BigInteger e = decodeBigInt(bb);
            BigInteger m = decodeBigInt(bb);
            RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e);
            return KeyFactory.getInstance("RSA").generatePublic(spec);

        }
        else {
            throw new IllegalArgumentException("Only supports RSA");
        }
    }

    private static BigInteger decodeBigInt(ByteBuffer bb) {
        int len = bb.getInt();
        byte[] bytes = new byte[len];
        bb.get(bytes);
        return new BigInteger(bytes);
    }


    public static PublicKey readPubFile(File file) throws IOException {
        String pubContent = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
        try {
            if(pubContent.startsWith(RSA_KEY)){
                return decodePublicKey(pubContent.split(" ")[1].getBytes());
            }
            return decodePublicKey(pubContent.split(" ")[0].getBytes());
        } catch (GeneralSecurityException e) {
            throw new IOException(e);
        }



    }
}
